package com.smmisia.shop.listener;

import com.alibaba.fastjson2.JSON;
import com.smmisia.shop.constant.TradeOrderEvent;
import com.smmisia.shop.constant.TradeOrderState;
import com.smmisia.shop.entity.TradeOrder;
import com.smmisia.shop.exception.ProductException;
import com.smmisia.shop.mapper.TradeOrderMapper;
import com.smmisia.shop.param.MessageBody;
import com.smmisia.shop.request.*;
import com.smmisia.shop.response.ProductInventoryResponse;
import com.smmisia.shop.service.ProductInventoryStreamService;
import com.smmisia.shop.service.ProductService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;

import java.util.function.Consumer;

import static com.smmisia.shop.exception.ProductErrorCode.PRODUCT_INVENTORY_UPDATE_FAILED;

@Slf4j
@Component
public class TradeOrderListener {

    @Autowired
    private ProductInventoryStreamService productInventoryStreamService;

    @Autowired
    private ProductService productService;

    @Autowired
    private TradeOrderMapper tradeOrderMapper;

    @Bean
    Consumer<Message<MessageBody>> orderClose() {
        return msg -> {
            log.info("receive order close message: {}", msg);
            String messageId = msg.getHeaders().get("ROCKET_MQ_MESSAGE_ID", String.class);
            String closeType = msg.getHeaders().get("CLOSE_TYPE", String.class);
            BaseOrderUpdateRequest orderUpdateRequest;
            if (TradeOrderEvent.CANCEL.name().equals(closeType)) {
                orderUpdateRequest = JSON.parseObject(msg.getPayload().getBody(), OrderCancelRequest.class);
            } else if (TradeOrderEvent.TIME_OUT.name().equals(closeType)) {
                orderUpdateRequest = JSON.parseObject(msg.getPayload().getBody(), OrderTimeoutRequest.class);
            } else {
                throw new UnsupportedOperationException("unsupported closeType " + closeType);
            }

            log.info("Received OrderClose Message  messageId:{},orderCloseRequest:{}，closeType:{}", messageId, JSON.toJSONString(orderUpdateRequest), closeType);

            TradeOrder tradeOrder = tradeOrderMapper.selectByOrderId(orderUpdateRequest.getOrderId());
            if(tradeOrder == null){
                log.error("trade order is not exist,orderCloseRequest:{}", JSON.toJSONString(orderUpdateRequest));
                throw new ProductException(PRODUCT_INVENTORY_UPDATE_FAILED);
            }
            if (tradeOrder.getOrderState() != TradeOrderState.CLOSED) {
                log.error("trade order state is illegal ,orderCloseRequest:{} , tradeOrderVO : {}", JSON.toJSONString(orderUpdateRequest), JSON.toJSONString(tradeOrder));
                throw new ProductException(PRODUCT_INVENTORY_UPDATE_FAILED);
            }
            ProductCancelSaleRequest collectionCancelSaleRequest = new ProductCancelSaleRequest(Long.valueOf(tradeOrder.getGoodsId()),Long.valueOf(tradeOrder.getItemCount()),orderUpdateRequest.getOrderId());
            Boolean cancelSaleResult = productService.cancelSale(collectionCancelSaleRequest);
            if (!cancelSaleResult) {
                log.error("cancelSale failed,orderCloseRequest:{} , collectionSaleResponse : {}", JSON.toJSONString(orderUpdateRequest), JSON.toJSONString(cancelSaleResult));
                throw new ProductException(PRODUCT_INVENTORY_UPDATE_FAILED);
            }
            InventoryRequest collectionInventoryRequest = new InventoryRequest();
            collectionInventoryRequest.setProductId(tradeOrder.getGoodsId());
            collectionInventoryRequest.setInventory(tradeOrder.getItemCount());
            collectionInventoryRequest.setIdentifier(orderUpdateRequest.getOrderId());
            ProductInventoryResponse decreaseResponse = productInventoryStreamService.increase(collectionInventoryRequest);
            if (decreaseResponse.getSuccess()) {
                log.info("decrease success,collectionInventoryRequest:{}", collectionInventoryRequest);
            } else {
                log.error("increase inventory failed,orderCloseRequest:{} , decreaseResponse : {}", JSON.toJSONString(orderUpdateRequest), JSON.toJSONString(decreaseResponse));
                throw new ProductException(PRODUCT_INVENTORY_UPDATE_FAILED);
            }
        };
    }
}
